<?php

class Page
{
    /**
     * @var TemplateEngine
     */
    protected $tmpl;
    /**
     * @var PageInfo
     */
    private $pageInfo;
    private $bodyTemplate = null;

    private $top = '';
    private $left = '';
    private $right = '';
    private $bottom = '';
    private $showLayout = true;

    private $selected = '';

    private $subBreadcrumbsChain = array();

    /**
     * @var ThemeInfo
     */
    protected $themeInfo;
    protected $errors = array();
    protected $isValid = true;

    protected $topMenuVar = array();

    private $user = null;
    /**
     * @var AccountInfo
     */
    protected $accountInfo = null;

    private $contentServerUrl = '';

    public static function Create( PageInfo $pageInfo, $showBreadcrumbs )
    {
        if ( $pageInfo->class )
        {
            $class = $pageInfo->class;
            return new $class( $pageInfo, $showBreadcrumbs );
        }

        return new self( $pageInfo, $showBreadcrumbs );
    }

    public function __construct( PageInfo $pageInfo, $showBreadscrumbs )
    {
        $this->tmpl             = Core::CreateTemplateEngine();
        $this->pageInfo         = $pageInfo;
        $this->showBreadscrumbs = $showBreadscrumbs;
        $this->bodyTemplate     = $pageInfo->tplFile;
        $this->contentServerUrl = Core::GetContentServerUrl();
        $themeInfo              = Core::ResourceManager()->GetThemesByID( $pageInfo->themeID );
        $this->themeInfo        = $themeInfo;

        if ( !empty($themeInfo->showBreadcrumbs ) && ( $themeInfo->showBreadcrumbs == "false" ) )
        {
            $this->showBreadscrumbs = false;
        }

        $user = Core::App()->GetUser();
        $this->SetUser($user);

        $this->Init();
    }

    public function Init()
    {
    }

    public function Process()
    {
    }

    /**
     * @return PageInfo
     */
    public function GetInfo()
    {
        return $this->pageInfo;
    }

    public function GetTemplateEngine()
    {
        return $this->tmpl;
    }

    public function GetUser()
    {
        return $this->user;
    }

    public function SetUser( $user )
    {
        $this->user = $user;

        if ($this->user instanceof SiteUser && $this->user->IsAuthenticated())
        {
            $this->accountInfo = $this->user->GetAccountInfo();
        }
        else
        {
            $this->accountInfo = null;
        }
    }

    public function GetAccountInfo()
    {
        return $this->accountInfo;
    }

    public function SetTitle( $title )
    {
        $this->pageInfo->title = $title;
    }
    
    public function SetName( $name )
    {
        $this->pageInfo->name = $name;
    }

    public function SetDescription( $description )
    {
        $this->pageInfo->description = $description;
    }

    public function ParseTemplate( $varName, $templateFile, $vars = null )
    {
        $tag = md5($templateFile);
        $this->tmpl->define( $tag, $templateFile );
        if (!is_null($vars))
        {
            $this->tmpl->set($vars);
        }
        $this->tmpl->parse( $varName, $tag );
    }

    public function SetVar($name, $value)
    {
        $this->tmpl->set($name, $value);
    }

    public function SetArrVar( $name, $value )
    {
        $this->tmpl->setArr( $name, $value );
    }

    public function SetQuotedVar($name, $value)
    {
        $this->tmpl->set($name, Util::GetHtmlEntities($value));
    }

    /**
     * Enables layout
     *
     */
    public function EnableLayout()
    {
        $this->showLayout = true;
    }

    /**
     * Disables layout
     *
     */
    public function DisableLayout()
    {
        $this->showLayout = false;
    }

    public function SetBodyTemplate( $templateFile )
    {
        $this->bodyTemplate = $templateFile;
    }

    public function SetBodyContent( $content )
    {
        $this->tmpl->set("CONTENT", $content);
    }

    public function SetSelectedMenu( $selected )
    {
        $this->selected = $selected;
    }

    /**
     * Creates combined CSS and JS files for the page
     */
    public function CreateCachedResources()
    {
        CacheUtils::GetPageCachedCssFiles( $this->pageInfo, $this->themeInfo->stylesheets );
        CacheUtils::GetPageCachedJsFiles( $this->pageInfo->id, $this->pageInfo->javascripts, $this->themeInfo->javascripts );
    }

    public function Display()
    {
        $pageInfo = $this->pageInfo;

        $id = $pageInfo->id;
        $isStaticPage = $this->IsStatic();

        // content
        $content = null;

        if ( $isStaticPage )
        {
            $cacheId = "html/$id/page_content";
            $content = Core::Cache()->Get($cacheId);
        }

        $this->tmpl->set('IS_AUTH', $this->user->IsAuthenticated());

        if ( is_null($content) )
        {
            $content = $this->tmpl->get('CONTENT');
            if ( empty($content) )
            {
                $this->tmpl->define("content", $this->bodyTemplate);
                if ( $pageInfo->comments )
                {
                    $comments = new Comments($id);
                    $comments->Update();
                    $this->tmpl->set('COMMENTS', $comments->Generate());
                }
                $this->tmpl->set('STATS_BASE_URL', Core::GetStatisticsBaseUrl());
                $this->tmpl->parse("CONTENT", "content");
                $content = $this->tmpl->getGenerated();
            }

            if ( $isStaticPage && !empty($content) )
            {
                Core::Cache()->Set($cacheId, $content);
            }
        }

        // retrieve visitor cookie from URL and set it if is present
        $visitorCookie = Request::Get(VISITOR_COOKIE_NAME);
        if ($visitorCookie && $visitorCookie != Request::GetCookie(VISITOR_COOKIE_NAME))
        {
            Response::SetCookie(VISITOR_COOKIE_NAME, $visitorCookie, time() + VISITOR_COOKIE_LIFETIME);
        }

        if ($this->showLayout)
        {
            $top = $this->GenerateTop();

            // do this after content and top were generated because all template
            // vars are removed
            $left = $this->GenerateLeft();
            $right = $this->GenerateRight();
            $bottom = $this->GenerateBottom();

            echo $top, $left, $content, $right, $bottom;
        }
        else
        {
            echo $content;
        }
    }

    public function SetError($message)
    {
        $this->errors[] = $message;
        $this->setValid(false);
    }

    public function GetErrors()
    {
        return $this->errors;
    }

    public function ClearErrors()
    {
        $this->errors = array();
    }

    public function IsValid()
    {
        return $this->isValid;
    }

    public function SetValid($isValid)
    {
        $this->isValid = $isValid;
    }

    /**
     * Sets sub breadcrumps for page.
     *
     * @param array of PathInfo Objects $subBreadcrumbsChain
     */
    public function SetSubBreadcrumbsChain( $subBreadcrumbsChain )
    {
        $this->subBreadcrumbsChain = $subBreadcrumbsChain;
    }

    /**
     * Returns sub breadcrumps of page.
     *
     */
    public function GetSubBreadcrumbsChain()
    {
        return $this->subBreadcrumbsChain;
    }

    /**
     * Returns true if page is static.
     *
     * @return unknown
     */
    public function IsStatic()
    {
        $isStaticPage = $this->pageInfo->static && !$this->pageInfo->comments;

        return $isStaticPage;
    }

    /**
     * Removes top from cache
     */
    public function ResetTop()
    {
        Core::Cache()->Remove( $this->GetTopCacheId() );
    }

    /**
     * Generates top part of page.
     *
     */
    private function GenerateTop()
    {
        $top = "";
        $pageInfo = $this->pageInfo;
        $id = $pageInfo->id;

        $this->tmpl->clearAll();
        $this->tmpl->define("top", $this->themeInfo->top);
        $cachedCssFiles = CacheUtils::GetPageCachedCssFiles( $pageInfo, $this->themeInfo->stylesheets );
        $this->tmpl->set( array(
            "PAGE_ID"           =>  $pageInfo->id,
            "PAGE_TITLE"        =>  $pageInfo->title,
            "PAGE_DESCRIPTION"  =>  $pageInfo->description,
            "PAGE_KEYWORDS"     =>  $pageInfo->keywords,
            "STYLESHEETS"       =>  $this->GetStylesheets( $cachedCssFiles ),
            "HOST"              =>  stristr(SITE_URL, '://'),
            "IS_AUTH"           =>  $this->user->IsAuthenticated(),
            "HAS_SEO_BLOCK"     =>  (isset($pageInfo->seoBlock) && !empty($pageInfo->seoBlock))
        ) );

        $this->tmpl->set( "CANONICAL_LINK", $this->GetCanonicalLink());

        if ( $this->user instanceof SiteUser )
        {
            if ( $this->user->IsAuthenticated() )
            {
                $account = SiteAccountUtils::GetAccountInfoById( $this->user->GetAccountId() );
                $this->tmpl->set( array(
                    "FIRST_NAME" => $account->firstName,
                    "LAST_NAME"  => $account->lastName
                ) );
            }
        }

        $this->SetAdditionalTopVars();

        $parentPageInfo = $this->pageInfo;
        if ( isset($parentPageInfo->parent) && $parentPageInfo->id != 'Index' )
        {
            while( $parentPageInfo->parent != 'Index')
            {
                $parentPageInfo = Pages::GetPageInfo($parentPageInfo->parent);
            }
        }
        $this->tmpl->set("PARENT_ID", $parentPageInfo->id);

        if ( $this->showBreadscrumbs )
        {
            $this->tmpl->set("BREADCRUMBS", Breadcrumbs::Generate( $id, $this->subBreadcrumbsChain ));
            $this->ParseTemplate("BREADCRUMBS", "include/breadcrumbs.tpl");
        }

        if ( $pageInfo->top && !empty( $this->themeInfo->top_menu ) )
        {
            $this->SetVar("TOP_MENU_EXPAND_ENABLED", $pageInfo->topMenuExpand ? 1 : 0);
            $this->tmpl->set($this->topMenuVar);
            $this->SetTopMenuParams();
            $this->ParseTemplate("TOP_MENU", $this->themeInfo->top_menu );
        }

        $this->tmpl->parse("TOP", "top");
        $top = $this->tmpl->GetGenerated();

        return $top;
    }

    /**
     * override this, to add special vars to top part page
     */
    public function SetAdditionalTopVars()
    {
    }

    private function GenerateLeft()
    {
        $left = '';
        $pageInfo = $this->pageInfo;
        $id = $pageInfo->id;

        $this->tmpl->clearAll();
        if ( ( $pageInfo->left && ( $pageInfo->tplFile != 'error404.tpl') ) && !empty( $this->themeInfo->left ) )
        {
            $sidebar = $this->GetSidebar();
            $this->tmpl->define("left", $this->themeInfo->left );
            $this->tmpl->set("SIDEBARS", $sidebar->Generate( $id ));
            $this->tmpl->set("SELECTED", $this->selected);

            if (!empty($this->accountInfo))
            {
                $this->tmpl->set("HAS_PRIORITY_SUPPORT", $this->accountInfo->hasPrioritySupport);
                $this->tmpl->set("USER_NAME", Util::UrlSafeBase64Encode("{$this->accountInfo->firstName} {$this->accountInfo->lastName}"));
                $this->tmpl->set("USER_EMAIL", Util::UrlSafeBase64Encode($this->accountInfo->email));
                $this->tmpl->set("USER_COMPANY", Util::UrlSafeBase64Encode($this->accountInfo->company));
            }

            $this->tmpl->parse("LEFT", "left");
            $left = $this->tmpl->GetGenerated();
        }

        return $left;
    }

    private function GenerateRight()
    {
        $right = '';
        $pageInfo = $this->pageInfo;
        $id = $pageInfo->id;
        $this->tmpl->clearAll();
        if ( ( $pageInfo->right && ( $pageInfo->tplFile != 'error404.tpl') ) && !empty( $this->themeInfo->right ) )
        {
            $sidebar = $this->GetSidebar();//Sidebar::Generate( );
            $this->tmpl->define("right", $this->themeInfo->right );
            $this->tmpl->set("SIDEBARS", $sidebar->Generate( $id ));
            $this->tmpl->parse("RIGHT", "right");
            $right = $this->tmpl->GetGenerated();
        }

        return $right;
    }

    private function GenerateBottom()
    {
        $pageInfo = $this->pageInfo;
        $id       = $pageInfo->id;

        $this->tmpl->clearAll();
        $this->tmpl->set('STATS_BASE_URL', Core::GetStatisticsBaseUrl());
        $this->tmpl->set('SEO_BLOCK', $this->pageInfo->id == "Index");
        $this->tmpl->set('YEAR', date("Y"));
        $this->tmpl->set('IS_SECURE', Request::IsSecure());
        $this->tmpl->set('HAS_SEO_BLOCK', (isset($pageInfo->seoBlock) && !empty($pageInfo->seoBlock)));

        if ( $pageInfo->seoBlock && !empty( $pageInfo->seoBlock ))
        {
            $this->tmpl->define("seo_block", $pageInfo->seoBlock);
            $this->tmpl->parse("SEO_BLOCK", "seo_block");
        }

        if ( $pageInfo->bottom && !empty( $this->themeInfo->bottom_menu ))
        {
            $this->tmpl->define("bottom_menu", $this->themeInfo->bottom_menu);
            $this->tmpl->parse("BOTTOM_MENU", "bottom_menu");
        }

        if ( $pageInfo->featured_customers )
        {
            $this->SetVar("FEATURED_CUSTOMERS", true);
        }

        $cachedJsFiles    = CacheUtils::GetPageCachedJsFiles( $id, $pageInfo->javascripts, $this->themeInfo->javascripts );
        $this->tmpl->set( array(
            "JAVASCRIPTS"       =>  $this->GetJavascripts( $cachedJsFiles )
        ) );

        if ( $this->user->IsAuthenticated() &&  $this->user instanceof SiteUser)
        {
            $this->tmpl->set("SITE_ACCOUNT_ID", $this->user->GetAccountId());
        }
        else
        {
            $loginRequired = ( Session::GetValue('redirect_url', '') != '' ) ? 1 : 0;
            $this->tmpl->set("LOGIN_REQUIRED", $loginRequired);
        }

        $this->ParseTemplate("BOTTOM", $this->themeInfo->bottom);
        $bottom = $this->tmpl->GetGenerated();

        return $bottom;
    }

    protected function GetJavascriptIncludeTag($file)
    {
        $file = ( UrlHelper::GetHost($file) == null ) ? $this->contentServerUrl . $file : $file;
        return sprintf('<script type="text/javascript" src="%s"></script>', $file);
    }

    /**
     * Returns string with prepared page JavaScript links.
     *
     * @param array $jsFiles
     * @return string
     */
    protected function GetJavascripts( $jsFiles )
    {
        $html = '';
        if ( !empty( $jsFiles ) )
        {
            foreach ( $jsFiles as $javascript )
            {
                $html .= $this->GetJavascriptIncludeTag($javascript);
            }
        }

        return $html;
    }

    protected function GetStylesheetIncludeTag($file)
    {
        $file = ( UrlHelper::GetHost($file) == null ) ? $this->contentServerUrl . $file : $file;
        return sprintf('<link href="%s" type="text/css" rel="stylesheet" media="all" />', $file);
    }

    /**
     * Returns string with prepared page stylesheet links.
     * @param array $cssFiles
     * @return string
     */
    protected function GetStylesheets( $cssFiles )
    {
        $html = '';
        foreach ($cssFiles as $stylesheet)
        {
            $html .= $this->GetStylesheetIncludeTag( CacheUtils::GetStylesheetSpriteFile( $stylesheet ) );
        }

        return $html;
    }

    /**
     * Generates cache id for page.
     *
     * @return unknown
     */
    private function GetTopCacheId()
    {
        $id = $this->pageInfo->id;

        return "html/$id/top";
    }

    public function SetTopMenuVar($name, $value)
    {
        if (!empty($name))
        {
            $this->topMenuVar[$name] = $value;
        }
    }

    public function SetKeywords( $keywords )
    {
        $this->pageInfo->keywords = ( !empty($this->pageInfo->keywords) ) ?  ($this->pageInfo->keywords . ', ' . $keywords) : $keywords;
    }
    
    public function GetPanelContent( $panelId )
    {
        $sidebar = $this->GetSidebar();
        
        return $sidebar ? $sidebar->GeneratePanel( $this->pageInfo->id, $panelId ) : "";
    }

    /**
     * This function makes it possible to add parametrs
     * to top template from derived class
     */
    protected function SetTopMenuParams()
    {}
    
    protected function GetCanonicalLink()
    {
        if (!empty($this->pageInfo->canonical))
        {
            return SITE_URL . $this->pageInfo->canonical;
        }
        else
        {
            // always insert canonical URL to prevent indexing CDN urls
            return UrlHelper::RemoveUrlParams(Request::GetUri(), array());
        }
    }
    
    protected function GetSidebar()
    {      
        return new Sidebar();
    }

}

?>